<?php

namespace App\Services;

use App\Models\SystemLog;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log as LaravelLog;

/**
 * 日志服务
 * 提供统一的日志记录和管理功能
 */
class LogService
{
    /**
     * 缓存键前缀
     */
    private const CACHE_PREFIX = 'logs:';

    /**
     * 缓存过期时间（秒）
     */
    private const CACHE_TTL = 300; // 5分钟

    /**
     * 记录系统操作日志
     */
    public function logOperation(
        string $operationType,
        string $module,
        string $description,
        ?int $userId = null,
        ?string $targetType = null,
        ?int $targetId = null,
        ?array $oldValues = null,
        ?array $newValues = null,
        string $level = 'info',
        ?string $action = null,
        ?array $requestData = null
    ): SystemLog {
        try {
            $log = SystemLog::log(
                $operationType,
                $module,
                $description,
                $userId,
                $targetType,
                $targetId,
                $oldValues,
                $newValues,
                $level,
                $action,
                $requestData
            );

            // 同时记录到Laravel日志
            $context = [
                'log_id' => $log->id,
                'user_id' => $userId,
                'operation_type' => $operationType,
                'module' => $module,
                'target_type' => $targetType,
                'target_id' => $targetId,
            ];

            LaravelLog::log($level, $description, $context);

            return $log;
        } catch (\Exception $e) {
            // 如果数据库日志记录失败，至少记录到Laravel日志
            LaravelLog::error('系统日志记录失败', [
                'error' => $e->getMessage(),
                'operation_type' => $operationType,
                'module' => $module,
                'description' => $description,
            ]);

            throw $e;
        }
    }

    /**
     * 记录用户登录日志
     */
    public function logLogin(int $userId, string $username, string $ipAddress, ?string $userAgent = null): SystemLog
    {
        return $this->logOperation(
            'login',
            'auth',
            "用户 {$username} 登录系统",
            $userId,
            'User',
            $userId,
            null,
            null,
            'info',
            'login',
            [
                'ip_address' => $ipAddress,
                'user_agent' => $userAgent,
            ]
        );
    }

    /**
     * 记录用户登出日志
     */
    public function logLogout(int $userId, string $username): SystemLog
    {
        return $this->logOperation(
            'logout',
            'auth',
            "用户 {$username} 登出系统",
            $userId,
            'User',
            $userId,
            null,
            null,
            'info',
            'logout'
        );
    }

    /**
     * 记录数据创建日志
     */
    public function logCreate(string $module, int $userId, string $targetType, int $targetId, array $newValues, ?string $targetName = null): SystemLog
    {
        $description = "创建{$targetType}";
        if ($targetName) {
            $description .= "：{$targetName}";
        }

        return $this->logOperation(
            'create',
            $module,
            $description,
            $userId,
            $targetType,
            $targetId,
            null,
            $newValues,
            'info',
            'create'
        );
    }

    /**
     * 记录数据更新日志
     */
    public function logUpdate(string $module, int $userId, string $targetType, int $targetId, array $oldValues, array $newValues, ?string $targetName = null): SystemLog
    {
        $description = "更新{$targetType}";
        if ($targetName) {
            $description .= "：{$targetName}";
        }

        return $this->logOperation(
            'update',
            $module,
            $description,
            $userId,
            $targetType,
            $targetId,
            $oldValues,
            $newValues,
            'info',
            'update'
        );
    }

    /**
     * 记录数据删除日志
     */
    public function logDelete(string $module, int $userId, string $targetType, int $targetId, array $oldValues, ?string $targetName = null): SystemLog
    {
        $description = "删除{$targetType}";
        if ($targetName) {
            $description .= "：{$targetName}";
        }

        return $this->logOperation(
            'delete',
            $module,
            $description,
            $userId,
            $targetType,
            $targetId,
            $oldValues,
            null,
            'warning',
            'delete'
        );
    }

    /**
     * 记录文件操作日志
     */
    public function logFileOperation(string $operation, int $userId, string $fileName, string $filePath, ?int $fileSize = null): SystemLog
    {
        $operationNames = [
            'upload' => '上传文件',
            'download' => '下载文件',
            'delete' => '删除文件',
            'view' => '查看文件',
        ];

        $operationName = $operationNames[$operation] ?? $operation;

        return $this->logOperation(
            $operation,
            'file',
            "{$operationName}：{$fileName}",
            $userId,
            'File',
            null,
            null,
            null,
            'info',
            $operation,
            [
                'file_name' => $fileName,
                'file_path' => $filePath,
                'file_size' => $fileSize,
            ]
        );
    }

    /**
     * 记录权限操作日志
     */
    public function logPermissionOperation(string $operation, int $userId, string $permission, ?string $roleName = null): SystemLog
    {
        $description = "权限操作：{$operation} - {$permission}";
        if ($roleName) {
            $description .= " (角色：{$roleName})";
        }

        return $this->logOperation(
            'update',
            'permission',
            $description,
            $userId,
            'Permission',
            null,
            null,
            null,
            'warning',
            $operation,
            [
                'permission' => $permission,
                'role_name' => $roleName,
            ]
        );
    }

    /**
     * 获取日志统计信息
     */
    public function getStatistics(array $filters = []): array
    {
        $cacheKey = self::CACHE_PREFIX . 'statistics:' . md5(serialize($filters));

        return Cache::remember($cacheKey, self::CACHE_TTL, function () use ($filters) {
            $query = SystemLog::query();

            // 应用过滤条件
            if (isset($filters['user_id'])) {
                $query->where('user_id', $filters['user_id']);
            }

            if (isset($filters['module'])) {
                $query->where('module', $filters['module']);
            }

            if (isset($filters['level'])) {
                $query->where('level', $filters['level']);
            }

            if (isset($filters['date_from']) && isset($filters['date_to'])) {
                $query->whereBetween('created_at', [$filters['date_from'], $filters['date_to']]);
            }

            $stats = [
                'total_logs' => $query->count(),
                'level_distribution' => $query->clone()
                    ->selectRaw('level, COUNT(*) as count')
                    ->groupBy('level')
                    ->pluck('count', 'level')
                    ->toArray(),
                'module_distribution' => $query->clone()
                    ->selectRaw('module, COUNT(*) as count')
                    ->groupBy('module')
                    ->pluck('count', 'module')
                    ->toArray(),
                'operation_distribution' => $query->clone()
                    ->selectRaw('operation_type, COUNT(*) as count')
                    ->groupBy('operation_type')
                    ->pluck('count', 'operation_type')
                    ->toArray(),
                'recent_logs' => $query->clone()
                    ->orderBy('created_at', 'desc')
                    ->limit(10)
                    ->get()
                    ->toArray(),
            ];

            return $stats;
        });
    }

    /**
     * 清理过期日志
     */
    public function cleanupLogs(int $daysToKeep = 90): int
    {
        $cutoffDate = now()->subDays($daysToKeep);

        $deletedCount = SystemLog::where('created_at', '<', $cutoffDate)->delete();

        LaravelLog::info('清理过期日志', [
            'deleted_count' => $deletedCount,
            'cutoff_date' => $cutoffDate->toISOString(),
        ]);

        // 清除相关缓存
        Cache::forget(self::CACHE_PREFIX . 'statistics:*');

        return $deletedCount;
    }

    /**
     * 导出日志
     */
    public function exportLogs(array $filters = [], string $format = 'csv'): string
    {
        $query = SystemLog::with('user')->orderBy('created_at', 'desc');

        // 应用过滤条件
        if (isset($filters['user_id'])) {
            $query->where('user_id', $filters['user_id']);
        }

        if (isset($filters['module'])) {
            $query->where('module', $filters['module']);
        }

        if (isset($filters['level'])) {
            $query->where('level', $filters['level']);
        }

        if (isset($filters['date_from']) && isset($filters['date_to'])) {
            $query->whereBetween('created_at', [$filters['date_from'], $filters['date_to']]);
        }

        $logs = $query->get();

        if ($format === 'csv') {
            return $this->exportToCsv($logs);
        } elseif ($format === 'json') {
            return $this->exportToJson($logs);
        }

        throw new \InvalidArgumentException('不支持的导出格式：' . $format);
    }

    /**
     * 导出为CSV格式
     */
    private function exportToCsv($logs): string
    {
        $output = fopen('php://temp', 'r+');

        // 写入CSV头部
        fputcsv($output, [
            'ID', '用户名', '操作类型', '模块', '操作', '目标类型', '目标ID',
            '描述', 'IP地址', '级别', '创建时间'
        ]);

        // 写入数据
        foreach ($logs as $log) {
            fputcsv($output, [
                $log->id,
                $log->username,
                $log->operation_name,
                $log->module,
                $log->action,
                $log->target_type,
                $log->target_id,
                $log->description,
                $log->ip_address,
                $log->level,
                $log->created_at->format('Y-m-d H:i:s'),
            ]);
        }

        rewind($output);
        $csv = stream_get_contents($output);
        fclose($output);

        return $csv;
    }

    /**
     * 导出为JSON格式
     */
    private function exportToJson($logs): string
    {
        return $logs->toJson(JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
    }

    /**
     * 清除日志缓存
     */
    public function clearCache(): void
    {
        $keys = Cache::get('log_cache_keys', []);
        foreach ($keys as $key) {
            if (str_starts_with($key, self::CACHE_PREFIX)) {
                Cache::forget($key);
            }
        }

        LaravelLog::info('日志缓存已清除');
    }
}
